﻿namespace Beetle.Clients
{
    using Beetle;
    using System;
    using System.Collections.Generic;
    using System.Net.Sockets;
    using System.Runtime.CompilerServices;

    public class TcpAsynNode
    {
        private int _field_a;
        private int _field_b;
        private Action<TcpChannel> _field_c;
        private List<TcpChannel> _field_d = new List<TcpChannel>();
        [CompilerGenerated]
        private string _field_e;
        [CompilerGenerated]
        private int _field_f;
        [CompilerGenerated]
        private int _field_g;
        [CompilerGenerated]
        private int _field_h;
        [CompilerGenerated]
        private string _field_i;
        [CompilerGenerated]
        private Exception _field_j;
        [CompilerGenerated]
        private NodeStatus _field_k;

        public TcpAsynNode(string host, int port, int maxconnections, Action<TcpChannel> oncreate)
        {
            this._field_c = oncreate;
            this.Host =(host);
            this.Port =(port);
            this.MaxConnections = maxconnections;
            this.Status = NodeStatus.Error;
        }

        private TcpChannel a()
        {
            lock (this)
            {
                if (this._field_d.Count == 0)
                {
                    return null;
                }
                this._field_b++;
                if (this._field_b >= this._field_d.Count)
                {
                    this._field_b = 0;
                }
                return this._field_d[this._field_b];
            }
        }

        private void a(CreateChannelArgs A_0)
        {
            if (A_0.Error != SocketError.Success)
            {
                this.Status = NodeStatus.Error;
                this._field_a = Environment.TickCount;
                this.LastError =(new SocketException((int) A_0.Error));
            }
            else
            {
                lock (this)
                {
                    try
                    {
                        if (this._field_c != null)
                        {
                            this._field_c(A_0.Channel);
                        }
                        A_0.Channel.ChannelDisposed += new EventChannelDisposed(this.a);
                        TcpServer.SetKeepAliveValues(A_0.Channel.Socket, 0x2710, 0x1388);
                        A_0.Channel.BeginReceive();
                        this.Status = NodeStatus.None;
                        this._field_d.Add(A_0.Channel);
                    }
                    catch (Exception exception)
                    {
                        this.LastError =(exception);
                    }
                    finally
                    {
                        if (this._field_d.Count < this.MaxConnections)
                        {
                            this.b();
                        }
                    }
                }
            }
        }

        private void a(object A_0, ChannelDisposedEventArgs A_1)
        {
            lock (this._field_d)
            {
                this._field_d.Remove(A_1.Channel);
            }
            this.b();
        }

        private void b()
        {
            TcpServer.CreateClientAsync(this.Host, this.Port, new Action<CreateChannelArgs>(this.a));
        }

        public void CheckState()
        {
            lock (this)
            {
                if ((Environment.TickCount - this._field_a) > (this.DetectTime * 0x3e8))
                {
                    this._field_a = Environment.TickCount;
                    if (this.Status == NodeStatus.Error)
                    {
                        this.b();
                    }
                }
            }
        }

        public void Connect()
        {
            this.b();
        }

        public bool Send(object msg)
        {
            if (this._field_d.Count == 0)
            {
                return false;
            }
            TcpChannel channel = this.a();
            if (channel == null)
            {
                return false;
            }
            return channel.Send(msg);
        }

        public IList<TcpChannel> Channels
        {
            get
            {
                return this._field_d;
            }
        }

        public int DetectTime
        {
            [CompilerGenerated]
            get
            {
                return this._field_h;
            }
            [CompilerGenerated]
            set
            {
                this._field_h = value;
            }
        }

        public string Host
        {
            [CompilerGenerated]
            get
            {
                return this._field_e;
            }
            [CompilerGenerated]
            private set
            {
                this._field_e = value;
            }
        }

        public Exception LastError
        {
            [CompilerGenerated]
            get
            {
                return this._field_j;
            }
            [CompilerGenerated]
            internal set
            {
                this._field_j = value;
            }
        }

        public int MaxConnections
        {
            [CompilerGenerated]
            get
            {
                return this._field_g;
            }
            [CompilerGenerated]
            set
            {
                this._field_g = value;
            }
        }

        public string Name
        {
            [CompilerGenerated]
            get
            {
                return this._field_i;
            }
            [CompilerGenerated]
            set
            {
                this._field_i = value;
            }
        }

        public int Port
        {
            [CompilerGenerated]
            get
            {
                return this._field_f;
            }
            [CompilerGenerated]
            private set
            {
                this._field_f = value;
            }
        }

        public NodeStatus Status
        {
            [CompilerGenerated]
            get
            {
                return this._field_k;
            }
            [CompilerGenerated]
            set
            {
                this._field_k = value;
            }
        }
    }
}

